﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Runtime.Serialization.Json;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace MessagePush
{
    public class UmMsg
    {
        //http的域名
        private static String HOST = "http://sdk.open.api.igexin.com/apiex.htm";

        //正式
        private static String APPKEY = "58f72579f29d98325a0017b3";
        private static String MASTERSECRET = "k7jqo88kpt621cbtwd5qfkvm0kvr5zd7";

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="title">标题</param>
        /// <param name="desc">描述</param>
        /// <param name="content">内容</param>
        /// <param name="device_tokens">cid</param>
        /// <returns></returns>
        public static string SendMsg(string title, string desc, string content, string device_tokens)
        {
            string ret = "";
            UmParam d = new UmParam();

            d.appkey = APPKEY;
            d.device_tokens = device_tokens;
            d.timestamp = ConvertDateTimeInt(DateTime.Now);
            d.type = "unicast";

            //消息内容

            Umbody body = new Umbody();

            body.after_open = "go_app";
            body.icon = "logo.png";
            body.text = desc;
            body.ticker = desc;
            body.title = title;

            //消息体
            UmPayload payload = new UmPayload();
            payload.body = body;
            payload.extra = ParseFormJson<UMMessage>(content);
            //通知
            payload.display_type = "notification";

            d.payload = payload;

            string json = GetJson<UmParam>(d);

            string signStr = sign(json);

            ret = HttpPost("http://msg.umeng.com/api/send?sign=" + signStr, unicode_js_0(json).Replace(":", ": ").Replace(",", ", "));

            return ret;
        }
        /// <summary>
        /// 把对象序列化 JSON 字符串 
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj">对象实体</param>
        /// <returns>JSON字符串</returns>
        public static string GetJson<T>(T obj)
        {
            //记住 添加引用 System.ServiceModel.Web 
            /**
             * 如果不添加上面的引用,System.Runtime.Serialization.Json; Json是出不来的哦
             * */
            DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(T));
            using (MemoryStream ms = new MemoryStream())
            {
                json.WriteObject(ms, obj);
                string szJson = Encoding.UTF8.GetString(ms.ToArray());
                return szJson;
            }
        }
        /// <summary>
        /// 把JSON字符串还原为对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="szJson">JSON字符串</param>
        /// <returns>对象实体</returns>
        public static T ParseFormJson<T>(string szJson)
        {
            T obj = Activator.CreateInstance<T>();
            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(szJson)))
            {
                DataContractJsonSerializer dcj = new DataContractJsonSerializer(typeof(T));
                return (T)dcj.ReadObject(ms);
            }

        }
        public static string sign(string param)
        {

            string method = "POST";
            string url = "http://msg.umeng.com/api/send";

            string post_body = unicode_js_0(param).Replace(":", ": ").Replace(",", ", ");

            string sign = method + url + post_body + MASTERSECRET;

            sign = MD5(sign);

            return sign;

        }
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        private static string MD5(string s)
        {

            var x = new MD5CryptoServiceProvider();
            var bs = System.Text.Encoding.UTF8.GetBytes(s);
            bs = x.ComputeHash(bs);
            var str = new System.Text.StringBuilder();
            foreach (byte b in bs)
            {
                str.Append(b.ToString("x2").ToLower());
            }
            return str.ToString();
        }
        /// <summary>
        /// 中文转unicode（符合js规则的）
        /// </summary>
        /// <returns></returns>
        public static string unicode_js_0(string str)
        {
            var outStr = string.Empty;
            if (!string.IsNullOrEmpty(str))
            {
                for (int i = 0; i < str.Length; i++)
                {
                    if (Regex.IsMatch(str[i].ToString(), @"[\u4e00-\u9fa5]")) { outStr += "\\u" + ((int)str[i]).ToString("x"); }
                    else { outStr += str[i]; }
                }
            }
            return outStr;
        }

        /// <summary>
        /// post 访问
        /// </summary>
        /// <param name="url"></param>
        /// <param name="datas"></param>
        /// <returns></returns>
        public static string HttpPost(string url, string datas)
        {
            string result = "";
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "POST";
            req.ContentType = "application/json";

            try
            {
                #region 添加Post 参数  
                byte[] data = Encoding.UTF8.GetBytes(datas);
                req.ContentLength = data.Length;
                using (Stream reqStream = req.GetRequestStream())
                {
                    reqStream.Write(data, 0, data.Length);
                    reqStream.Close();
                }
                #endregion

                HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
                Stream stream = resp.GetResponseStream();
                //获取响应内容  
                using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
                {
                    result = reader.ReadToEnd();
                }
            }
            catch (WebException ex)
            {
                HttpWebResponse res = (HttpWebResponse)ex.Response;
                Stream myResponseStream = res.GetResponseStream();
                StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
                string retString = myStreamReader.ReadToEnd();
            }
            return result;

        }
        //private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        //{
        //    return true; //总是接受   
        //}
        /// <summary>
        /// DateTime时间格式转换为Unix时间戳格式
        /// </summary>
        /// <param name=”time”></param>
        /// <returns></returns>    
        public static long ConvertDateTimeInt(System.DateTime time)
        {
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
            return (long)(time - startTime).TotalMilliseconds;
        }

    }
    public class UmParam
    {
        /// <summary>
        /// 必填 应用唯一标识
        /// </summary>
        public string appkey { get; set; }

        /// <summary>
        /// 必填 时间戳，10位或者13位均可，时间戳有效期为10分钟
        /// </summary>
        public long timestamp { get; set; }

        /// <summary>
        /// 可选 设备唯一表示
        /// 当type=unicast时,必填, 表示指定的单个设备
        /// 当type = listcast时, 必填, 要求不超过500个,
        /// 多个device_token以英文逗号间隔
        /// </summary>
        public string device_tokens { get; set; }

        /// <summary>
        /// 必填 消息发送类型,其值可以为:
        /// unicast-单播
        /// listcast-列播(要求不超过500个device_token)
        ///   filecast-文件播
        /// (多个device_token可通过文件形式批量发送）
        /// broadcast-广播
        /// groupcast-组播
        ///  (按照filter条件筛选特定用户群, 具体请参照filter参数)
        ///customizedcast(通过开发者自有的alias进行推送), 
        /// 包括以下两种case:
        ///    - alias: 对单个或者多个alias进行推送
        ///  - file_id: 将alias存放到文件后，根据file_id来推送
        /// </summary>
        public string type { get; set; }

        /// <summary>
        /// 消息内容(Android最大为1840B), 包含参数说明如下(JSON格式):
        /// </summary>
        public UmPayload payload { get; set; }
    }

    public class UmPayload
    {
        /// <summary>
        /// 消息体
        /// </summary>
        public Umbody body { get; set; }
        /// <summary>
        /// 消息类型，值可以为:   notification-通知，message-消息
        /// </summary>
        public string display_type { get; set; }
        /// <summary>
        /// 可选 用户自定义key-value。只对"通知"
        /// </summary>
        public UMMessage extra { get; set; }
    }

    public class Umbody
    {
        /// <summary>
        /// 通知栏提示文字
        /// </summary>
        public string ticker { get; set; }

        /// <summary>
        /// 通知标题
        /// </summary>
        public string title { get; set; }

        /// <summary>
        /// 必填 通知文字描述 
        /// </summary>
        public string text { get; set; }

        /// <summary>
        /// 点击"通知"的后续行为，默认为打开app。
        /// "go_app": 打开应用
        /// "go_url": 跳转到URL
        /// "go_activity": 打开特定的activity
        /// "go_custom": 用户自定义内容。
        /// </summary>
        public string after_open { get; set; }

        /// <summary>
        ///  自定义通知图标:
        /// </summary>
        public string icon { get; set; }
    }

    /// <summary>
    /// 消息主体
    /// </summary>
    public class UMMessage
    {
        /// <summary>
        /// 发送用户编码
        /// </summary>
        public string fCustomId { get; set; }
        /// <summary>
        /// 如果是商户 小区名+开店类型+昵称
        /// </summary>
        public string fName { get; set; }
        /// <summary>
        /// 发送用户图像
        /// </summary>
        public string fAvatar { get; set; }
        /// <summary>
        /// 接收用户编码
        /// </summary>
        public string sCustomId { get; set; }
        /// <summary>
        /// 接收用户名称
        /// </summary>
        public string sName { get; set; }
        /// <summary>
        /// 接收用户图像
        /// </summary>
        public string sAvatar { get; set; }
        /// <summary>
        /// 消息发送时间
        /// </summary>
        public string msgTime { get; set; }
        /// <summary>
        /// 消息阅读时间
        /// </summary>
        public string msgRedtime { get; set; }

        /// <summary>
        ///   1提醒  2 web消息 3 聊天 4-10业务消息(4订单)
        /// </summary>
        public string type1 { get; set; }
        /// <summary>
        ///   (3即时通讯 :1正常聊天消息,2时间通知)
        /// </summary>
        public string type2 { get; set; }
        /// <summary>
        /// 业务编码
        /// </summary>
        public string bussCode { get; set; }
        /// <summary>
        ///  状态  (1未读 2已读3已清空)
        /// </summary>
        public string status { get; set; }
        /// <summary>
        /// 内容
        /// </summary>
        public UMContent content { get; set; }
    }
    /// <summary>
    /// 消息内容
    /// </summary>
    public class UMContent
    {
        /// <summary>
        /// 1图片 2内容 3图片+内容
        /// </summary>
        public string msgType { get; set; }
        /// <summary>
        /// 内容
        /// </summary>
        public string texts { get; set; }
        /// <summary>
        /// 图片地址
        /// </summary>
        public string img { get; set; }
    }
}
